<script>
    import ElCollapseTransition from 'element-ui/src/transitions/collapse-transition';
    import menuMixin from './menu-mixin';
    import Emitter from 'element-ui/src/mixins/emitter';
    import Popper from 'element-ui/src/utils/vue-popper';

    const poperMixins = {
        props: {
            transformOrigin: {
                type: [Boolean, String],
                default: false
            },
            offset: Popper.props.offset,
            boundariesPadding: Popper.props.boundariesPadding,
            popperOptions: Popper.props.popperOptions
        },
        data: Popper.data,
        methods: Popper.methods,
        beforeDestroy: Popper.beforeDestroy,
        deactivated: Popper.deactivated
    };

    export default {
        name: 'ElSubmenu',

        componentName: 'ElSubmenu',

        mixins: [menuMixin, Emitter, poperMixins],

        components: {ElCollapseTransition},

        props: {
            index: {
                type: String,
                required: true
            },
            showTimeout: {
                type: Number,
                default: 300
            },
            hideTimeout: {
                type: Number,
                default: 300
            },
            popperClass: String,
            disabled: Boolean,
            popperAppendToBody: {
                type: Boolean,
                default: undefined
            }
        },

        data() {
            return {
                popperJS: null,
                timeout: null,
                items: {},
                submenus: {},
                mouseInChild: false
            };
        },
        watch: {
            opened(val) {
                if (this.isMenuPopup) {
                    this.$nextTick(_ => {
                        this.updatePopper();
                    });
                }
            }
        },
        computed: {
            // popper option
            appendToBody() {
                return this.popperAppendToBody === undefined
                    ? this.isFirstLevel
                    : this.popperAppendToBody;
            },
            menuTransitionName() {
                return this.rootMenu.collapse ? 'el-zoom-in-left' : 'el-zoom-in-top';
            },
            opened() {
                return this.rootMenu.openedMenus.indexOf(this.index) > -1;
            },
            active() {
                let isActive = false;
                const submenus = this.submenus;
                const items = this.items;

                Object.keys(items).forEach(index => {
                    if (items[index].active) {
                        isActive = true;
                    }
                });

                Object.keys(submenus).forEach(index => {
                    if (submenus[index].active) {
                        isActive = true;
                    }
                });

                return isActive;
            },
            hoverBackground() {
                return this.rootMenu.hoverBackground;
            },
            backgroundColor() {
                return this.rootMenu.backgroundColor || '';
            },
            activeTextColor() {
                return this.rootMenu.activeTextColor || '';
            },
            textColor() {
                return this.rootMenu.textColor || '';
            },
            mode() {
                return this.rootMenu.mode;
            },
            isMenuPopup() {
                return this.rootMenu.isMenuPopup;
            },
            titleStyle() {
                if (this.mode !== 'horizontal') {
                    return {
                        color: this.textColor
                    };
                }
                return {
                    borderBottomColor: this.active
                        ? (this.rootMenu.activeTextColor ? this.activeTextColor : '')
                        : 'transparent',
                    color: this.active
                        ? this.activeTextColor
                        : this.textColor
                };
            },
            isFirstLevel() {
                let isFirstLevel = true;
                let parent = this.$parent;
                while (parent && parent !== this.rootMenu) {
                    if (['ElSubmenu', 'ElMenuItemGroup'].indexOf(parent.$options.componentName) > -1) {
                        isFirstLevel = false;
                        break;
                    } else {
                        parent = parent.$parent;
                    }
                }
                return isFirstLevel;
            }
        },
        methods: {
            handleCollapseToggle(value) {
                if (value) {
                    this.initPopper();
                } else {
                    this.doDestroy();
                }
            },
            addItem(item) {
                this.$set(this.items, item.index, item);
            },
            removeItem(item) {
                delete this.items[item.index];
            },
            addSubmenu(item) {
                this.$set(this.submenus, item.index, item);
            },
            removeSubmenu(item) {
                delete this.submenus[item.index];
            },
            handleClick() {
                const {rootMenu, disabled} = this;
                if (
                    (rootMenu.menuTrigger === 'hover' && rootMenu.mode === 'horizontal') ||
                    (rootMenu.collapse && rootMenu.mode === 'vertical') ||
                    disabled
                ) {
                    return;
                }
                this.dispatch('ElMenu', 'submenu-click', this);
            },
            handleMouseenter(event, showTimeout = this.showTimeout) {

                if (!('ActiveXObject' in window) && event.type === 'focus' && !event.relatedTarget) {
                    return;
                }
                const {rootMenu, disabled} = this;
                if (
                    (rootMenu.menuTrigger === 'click' && rootMenu.mode === 'horizontal') ||
                    (!rootMenu.collapse && rootMenu.mode === 'vertical') ||
                    disabled
                ) {
                    return;
                }
                this.dispatch('ElSubmenu', 'mouse-enter-child');
                clearTimeout(this.timeout);
                this.timeout = setTimeout(() => {
                    this.rootMenu.openMenu(this.index, this.indexPath);
                }, showTimeout);

                if (this.appendToBody) {
                    this.$parent.$el.dispatchEvent(new MouseEvent('mouseenter'));
                }
            },
            handleMouseleave(deepDispatch = false) {
                const {rootMenu} = this;
                if (
                    (rootMenu.menuTrigger === 'click' && rootMenu.mode === 'horizontal') ||
                    (!rootMenu.collapse && rootMenu.mode === 'vertical')
                ) {
                    return;
                }
                this.dispatch('ElSubmenu', 'mouse-leave-child');
                clearTimeout(this.timeout);
                this.timeout = setTimeout(() => {
                    !this.mouseInChild && this.rootMenu.closeMenu(this.index);
                }, this.hideTimeout);

                if (this.appendToBody && deepDispatch) {
                    if (this.$parent.$options.name === 'ElSubmenu') {
                        this.$parent.handleMouseleave(true);
                    }
                }
            },
            handleTitleMouseenter() {
                if (this.mode === 'horizontal' && !this.rootMenu.backgroundColor) return;
                const title = this.$refs['submenu-title'];
                title && (title.style.backgroundColor = this.rootMenu.hoverBackground);
            },
            handleTitleMouseleave() {
                if (this.mode === 'horizontal' && !this.rootMenu.backgroundColor) return;
                const title = this.$refs['submenu-title'];
                title && (title.style.backgroundColor = this.rootMenu.backgroundColor || '');
            },
            updatePlacement() {
                this.currentPlacement = this.mode === 'horizontal' && this.isFirstLevel
                    ? 'bottom-start'
                    : 'right-start';
            },
            initPopper() {
                this.referenceElm = this.$el;
                this.popperElm = this.$refs.menu;
                this.updatePlacement();
            }
        },
        created() {
            this.$on('toggle-collapse', this.handleCollapseToggle);
            this.$on('mouse-enter-child', () => {
                this.mouseInChild = true;
                clearTimeout(this.timeout);
            });
            this.$on('mouse-leave-child', () => {
                this.mouseInChild = false;
                clearTimeout(this.timeout);
            });
        },
        mounted() {
            this.parentMenu.addSubmenu(this);
            this.rootMenu.addSubmenu(this);
            this.initPopper();
        },
        beforeDestroy() {
            this.parentMenu.removeSubmenu(this);
            this.rootMenu.removeSubmenu(this);
        },
        render(h) {
            const {
                active,
                opened,
                paddingStyle,
                titleStyle,
                backgroundColor,
                rootMenu,
                currentPlacement,
                menuTransitionName,
                mode,
                disabled,
                popperClass,
                $slots,
                isFirstLevel
            } = this;

            const popupMenu = (
                < transition
            name = {menuTransitionName} >
                < div
            ref = "menu"
            v - show = {opened}
        class
            = {[`el-menu--${mode}`, popperClass
        ]
        }
            on - mouseenter = {($event)
        =>
            this.handleMouseenter($event, 100)
        }
            on - mouseleave = {()
        =>
            this.handleMouseleave(true)
        }
            on - focus = {($event)
        =>
            this.handleMouseenter($event, 100)
        }>
        <
            ul
            role = "menu"
        class
            = {['el-menu el-menu--popup',`el-menu--popup-${currentPlacement}`
        ]
        }
            style = {
            {
                backgroundColor: rootMenu.backgroundColor || ''
            }
        }>
            {
                $slots.default
            }
        <
            /ul>
            < /div>
            < /transition>
        )
            ;

            const inlineMenu = (
                < el - collapse - transition >
                < ul
            role = "menu"
        class
            = "el-menu el-menu--inline"
            v - show = {opened}
            style = {
            {
                backgroundColor: rootMenu.backgroundColor || ''
            }
        }>
            {
                $slots.default
            }
        <
            /ul>
            < /el-collapse-transition>
        )
            ;

            const submenuTitleIcon = (
                rootMenu.mode === 'horizontal' && isFirstLevel ||
                rootMenu.mode === 'vertical' && !rootMenu.collapse
            ) ? 'el-icon-arrow-down' : 'el-icon-arrow-right';

            return (
                < li
        class
            = {
            {
                'el-submenu'
            :
                true,
                    'is-active'
            :
                active,
                    'is-opened'
            :
                opened,
                    'is-disabled'
            :
                disabled
            }
        }
            role = "menuitem"
            aria - haspopup = "true"
            aria - expanded = {opened}
            on - mouseenter = {this.handleMouseenter
        }
            on - mouseleave = {()
        =>
            this.handleMouseleave(false)
        }
            on - focus = {this.handleMouseenter
        }
        >
        <
            div
        class
            = "el-submenu__title"
            ref = "submenu-title"
            on - click = {this.handleClick
        }
            on - mouseenter = {this.handleTitleMouseenter
        }
            on - mouseleave = {this.handleTitleMouseleave
        }
            style = {[paddingStyle, titleStyle,
            {
                backgroundColor
            }
        ]
        }
        >
            {
                $slots.title
            }
        <
            i
        class
            = {['el-submenu__icon-arrow', submenuTitleIcon
        ]
        }><
            /i>
            < /div>
            {
                this.isMenuPopup ? popupMenu : inlineMenu
            }
        <
            /li>
        )
            ;
        }
    };
</script>
